using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Collections;
using System.Reflection;
using System.Diagnostics;
using System.Xml;

namespace Common
{
    /// <summary>
    /// 
    /// </summary>
    public class ConfigUtil : System.Configuration.AppSettingsReader
    {
        /// <summary>
        /// 
        /// </summary>
        public enum ConfigFileType
        {
            /// <summary></summary>
            AppConfig = 0,
            /// <summary></summary>
            WebConfig = 1
        }

        private string _ConfigFilePath = string.Empty;
        private XmlNode _Node = null;
        private ConfigFileType _ConfigType = ConfigFileType.AppConfig;

        /// <summary>
        /// 
        /// </summary>
        public ConfigFileType ConfigType
        {
            get { return _ConfigType; }
            set { _ConfigType = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool SetValue(string key, string value)
        {
            XmlDocument xDoc = new XmlDocument();
            xDoc = this.LoadConfigDoc(xDoc);
            this._Node = xDoc.SelectSingleNode("//appSettings");
            if (this._Node == null)
                throw new Exception("appSetting section not found");

            try
            {
                XmlElement addElem = (XmlElement)this._Node.SelectSingleNode("//add[@key=\"" +
                    key + "\"]");
                if (addElem != null)
                {
                    addElem.SetAttribute("value", value);
                }
                else
                {
                    XmlElement entry = xDoc.CreateElement("add");
                    entry.SetAttribute("key", key);
                    entry.SetAttribute("value", value);
                    this._Node.AppendChild(entry);
                }
                this.SaveConfigDoc(xDoc, this._ConfigFilePath);
                return true;
            }
            catch 
            {
                return false;
            }
        }

        private XmlDocument LoadConfigDoc(XmlDocument xDoc)
        {
            if (this._ConfigType == ConfigFileType.AppConfig)
            {
                this._ConfigFilePath = System.Reflection.Assembly.GetEntryAssembly().Location;
                this._ConfigFilePath += ".config";
                if (!System.IO.File.Exists(this._ConfigFilePath))
                {
                    string binFolderPath = System.IO.Path.GetDirectoryName(this._ConfigFilePath);
                    System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(binFolderPath);
                    System.IO.FileInfo[] files = dirInfo.GetFiles();
                    foreach (System.IO.FileInfo file in files)
                    {
                        if (file.FullName.ToLower().EndsWith(".exe.config"))
                        {
                            this._ConfigFilePath = file.FullName;
                            break;
                        }
                    }
                }
                else
                {
                    // this._ConfigFilePath = System.Web.HttpContext.Current.Server.MapPath("web.config");
                }
            }
            xDoc.Load(this._ConfigFilePath);
            return xDoc;
        }

        private void SaveConfigDoc(XmlDocument xDoc, string path)
        {
            try
            {
                XmlTextWriter w = new XmlTextWriter(path, Encoding.Default);
                w.Formatting = Formatting.Indented;
                xDoc.WriteTo(w);
                w.Flush();
                w.Close();
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
            }
        }

        private bool RemoveElement(string key)
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc = this.LoadConfigDoc(xDoc);
                this._Node = xDoc.SelectSingleNode("//appSettings");
                if (this._Node == null)
                    throw new InvalidOperationException("Unable to find appSettings section from config file");

                this._Node.RemoveChild(this._Node.SelectSingleNode("//add[@key=\"" + key + "\"]"));
                this.SaveConfigDoc(xDoc, this._ConfigFilePath);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connName"></param>
        /// <param name="connStr"></param>
        public void SetDbConnection(string connName, string connStr)
        {
            XmlDocument xDoc = new XmlDocument();
            xDoc = this.LoadConfigDoc(xDoc);
            XmlNodeList connNodes=xDoc.SelectNodes("//connectionStrings/add");

            if (connNodes != null && connNodes.Count > 0)
            {
                bool found = false;
                foreach (XmlNode connNode in connNodes)
                {
                    string existingConnName = connNode.Attributes.GetNamedItem("name").Value;
                    if (existingConnName == connName)
                    {
                        found = true;
                        connNode.Attributes.GetNamedItem("connectionString").Value = connStr;
                    }
                }
                if (!found)
                {
                    XmlNode connRootNode = xDoc.SelectSingleNode("//connectionStrings");
                    XmlNode newConnNode = XmlDataUtil.AddElement(ref xDoc, connRootNode, "add");
                    XmlDataUtil.UpdateAttribute(ref xDoc, newConnNode, "name", connName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, newConnNode, "connectionString", connStr);
                }
            }
            else
            {
                XmlNode connRootNode = XmlDataUtil.AddElement(ref xDoc, xDoc.DocumentElement, "connectionStrings");
                XmlNode newConnNode = XmlDataUtil.AddElement(ref xDoc, connRootNode, "add");
                XmlDataUtil.UpdateAttribute(ref xDoc, newConnNode, "name", connName);
                XmlDataUtil.UpdateAttribute(ref xDoc, newConnNode, "connectionString", connStr);
            }

            this.SaveConfigDoc(xDoc, this._ConfigFilePath);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="srcFilePath"></param>
        /// <param name="tgtFilePath"></param>
        public static void TransferConfigSettings(string srcFilePath, string tgtFilePath)
        {
        }
    }
}
